package org.gdstash.character;

import org.gdstash.file.GDReader;
import org.gdstash.file.GDWriter;
import org.gdstash.item.GDAbstractContainer;
import org.gdstash.item.GDItem;
import org.gdstash.util.FileVersionException;
import org.gdstash.util.GDMsgFormatter;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public class GDCharStash extends GDAbstractContainer {
    public static final int VERSION_5 = 5;
    public static final int VERSION_6 = 6;
    public static final int VERSION_8 = 8;
    private static final int BLOCK = 4;
    private int version;
    private GDChar gdc;
    private int numPages;
    private List<GDAbstractContainer> pages;

    public GDCharStash(final GDChar gdc) {
        super(3);
        this.gdc = gdc;
        this.pages = new LinkedList<GDAbstractContainer>();
    }

    public int getHeight() {
        if (this.pages == null) {
            return 18;
        }
        final GDAbstractContainer page = this.pages.get(0);
        if (page == null) {
            return 18;
        }
        return page.getContainerHeight();
    }

    public int getWidth() {
        if (this.pages == null) {
            return 10;
        }
        final GDAbstractContainer page = this.pages.get(0);
        if (page == null) {
            return 10;
        }
        return page.getContainerWidth();
    }

    public List<GDAbstractContainer> getStashPages() {
        return this.pages;
    }

    @Override
    public List<GDItem> getItemList() {
        final List<GDItem> list = new LinkedList<GDItem>();
        if (this.pages == null) {
            return list;
        }
        for (final GDAbstractContainer page : this.pages) {
            if (page != null) {
                list.addAll(page.getItemList());
            }
        }
        return list;
    }

    @Override
    public List<GDItem> getRemovedItemList() {
        final List<GDItem> list = new LinkedList<GDItem>();
        if (this.pages == null) {
            return list;
        }
        for (final GDAbstractContainer page : this.pages) {
            if (page != null) {
                list.addAll(page.getRemovedItemList());
            }
        }
        return list;
    }

    @Override
    public boolean addItem(final GDItem item) {
        if (this.pages == null) {
            return false;
        }
        final GDAbstractContainer page = this.pages.get(0);
        return page != null && page.addItem(item);
    }

    @Override
    public boolean removeItem(final GDItem item) {
        if (this.pages == null) {
            return false;
        }
        final GDAbstractContainer page = this.pages.get(0);
        return page != null && page.removeItem(item);
    }

    @Override
    public boolean hasChanged() {
        if (this.pages == null) {
            return false;
        }
        boolean changed = false;
        for (final GDAbstractContainer page : this.pages) {
            if (page.hasChanged()) {
                changed = true;
                break;
            }
        }
        return changed;
    }

    @Override
    public int getContainerHeight() {
        if (this.pages == null) {
            return 0;
        }
        final GDAbstractContainer page = this.pages.get(0);
        if (page == null) {
            return 0;
        }
        return page.getContainerHeight();
    }

    @Override
    public int getContainerWidth() {
        if (this.pages == null) {
            return 0;
        }
        final GDAbstractContainer page = this.pages.get(0);
        if (page == null) {
            return 0;
        }
        return page.getContainerWidth();
    }

    @Override
    public int getContainerType() {
        if (this.pages == null) {
            return 3;
        }
        final GDAbstractContainer page = this.pages.get(0);
        if (page == null) {
            return 3;
        }
        return page.getContainerType();
    }

    @Override
    public void refresh() {
        if (this.pages == null) {
            return;
        }
        for (final GDAbstractContainer page : this.pages) {
            if (page != null) {
                page.refresh();
            }
        }
    }

    public void read() throws IOException {
        int val = 0;
        final GDReader.Block block = new GDReader.Block();
        val = GDReader.readBlockStart(block);
        if (val != 4) {
            throw new FileVersionException(GDMsgFormatter.getString(GDMsgFormatter.rbMsg, "ERR_UNSUPPORTED_VERSION"));
        }
        this.version = GDReader.readEncInt(true);
        if (this.version != 5 && this.version != 6 && this.version != 8) {
            throw new FileVersionException(GDMsgFormatter.getString(GDMsgFormatter.rbMsg, "ERR_UNSUPPORTED_VERSION"));
        }
        if (this.version >= 6) {
            this.numPages = GDReader.readEncInt(true);
        } else {
            this.numPages = 1;
        }
        this.pages.clear();
        for (int i = 0; i < this.numPages; ++i) {
            final GDCharStashPage page = new GDCharStashPage(this.gdc, this.version);
            page.read(this.version);
            this.pages.add(page);
        }
        GDReader.readBlockEnd(block);
        this.changed = false;
    }

    public void write() throws IOException {
        final GDReader.Block block = new GDReader.Block();
        GDWriter.writeBlockStart(block, 4);
        GDWriter.writeInt(this.version);
        if (this.version >= 6) {
            GDWriter.writeInt(this.numPages);
        }
        for (GDAbstractContainer gdAbstractContainer : this.pages) {
            if (gdAbstractContainer instanceof GDCharStashPage) {
                GDCharStashPage page = (GDCharStashPage) gdAbstractContainer;
                page.write(this.version);
            }
        }
        GDWriter.writeBlockEnd(block);
        this.changed = false;
    }

    public int getByteSize() {
        int size = 0;
        size += 4;
        size += 4;
        size += 4;
        if (this.version >= 6) {
            size += 4;
        }
        for (GDAbstractContainer gdAbstractContainer : this.pages) {
            if (gdAbstractContainer instanceof GDCharStashPage) {
                GDCharStashPage page = (GDCharStashPage) gdAbstractContainer;
                size += page.getByteSize(this.version);
            }
        }
        size += 4;
        return size;
    }
}
